package top.guinguo.advance_04.searcher.util;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.apache.lucene.search.function.CustomScoreProvider;
import org.apache.lucene.search.function.CustomScoreQuery;
import org.apache.lucene.search.function.FieldScoreQuery;
import org.apache.lucene.search.function.ValueSourceQuery;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by guin_guo on 2016/12/29.
 */
public class MyScoreQuery {

    public void searchByScoreQuery() {
        try {
            IndexSearcher searcher = new IndexSearcher(IndexReader.open(FileIndexUtils.getDirectory()));
            Query q = new TermQuery(new Term("content", "java"));
            //1.创建一个评分域
            FieldScoreQuery fd = new FieldScoreQuery("score", FieldScoreQuery.Type.INT);
            //2. 根据评分域和原有的Query创建自定义的Query对象
            MyCustomScoreQuery query = new MyCustomScoreQuery(q, fd);
            TopDocs tds = null;
            tds = searcher.search(query, 100);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (ScoreDoc sd : tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println(sd.doc + ":(" + sd.score + ")" +
                        "[" + doc.get("filename") + "]" + "【" + doc.get("path") + "】--->" +
                        doc.get("size") + "----" + sdf.format(new Date(Long.valueOf(doc.get("date"))))
                );
            }
            searcher.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void searchByFileScoreQuery() {
        try {
            IndexSearcher searcher = new IndexSearcher(IndexReader.open(FileIndexUtils.getDirectory()));
            Query q = new TermQuery(new Term("content", "java"));
            //1.创建一个评分域
            MyFileScoreQuery query = new MyFileScoreQuery(q);
            TopDocs tds = null;
            tds = searcher.search(query, 100);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (ScoreDoc sd : tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println(sd.doc + ":(" + sd.score + ")" +
                        "[" + doc.get("filename") + "]" + "【" + doc.get("path") + "】--->" +
                        doc.get("size") + "----" + sdf.format(new Date(Long.valueOf(doc.get("date"))))
                );
            }
            searcher.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void searchByDateScoreQuery() {
        try {
            IndexSearcher searcher = new IndexSearcher(IndexReader.open(FileIndexUtils.getDirectory()));
            Query q = new TermQuery(new Term("content", "java"));
            //1.创建一个评分域
            MyDateScoreQuery query = new MyDateScoreQuery(q);
            TopDocs tds = null;
            tds = searcher.search(query, 100);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (ScoreDoc sd : tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println(sd.doc + ":(" + sd.score + ")" +
                        "[" + doc.get("filename") + "]" + "【" + doc.get("path") + "】--->" +
                        doc.get("size") + "----" + sdf.format(new Date(Long.valueOf(doc.get("date"))))
                );
            }
            searcher.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class MyDateScoreQuery extends CustomScoreQuery {

        public MyDateScoreQuery(Query subQuery) {
            super(subQuery);
        }

        @Override
        protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {
            return new MyDateScoreProvider(reader);
        }
    }
    private class MyDateScoreProvider extends CustomScoreProvider {

        long[] dates = null;

        /**
         * Creates a new instance of the provider class for the given {@link IndexReader}.
         *
         * @param reader
         */
        public MyDateScoreProvider(IndexReader reader) {
            super(reader);
            try {
                dates = FieldCache.DEFAULT.getLongs(reader, "date");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
            //1. 获取当前date数据 秒
            long date = dates[doc]/1000;
            //2. 获取今天的date数据
            long today = System.currentTimeMillis()/1000;
            //3. 一年为多少秒
//            long intval = 60 * 60 * 24 * 365;
            long intval = 60 * 60 * 24 * 90;
            if (today - date <= intval) {
                //三个月内，为其加分
                return subQueryScore * 10;
            }
            return super.customScore(doc, subQueryScore, valSrcScore);
        }
    }

    private class MyFileScoreQuery extends CustomScoreQuery {

        public MyFileScoreQuery(Query subQuery) {
            super(subQuery);
        }

        @Override
        protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {
            return new MyFileScoreProvider(reader);
        }
    }

    private class MyFileScoreProvider extends CustomScoreProvider {

        private String[] filenames = null;

        /**
         * Creates a new instance of the provider class for the given {@link IndexReader}.
         *
         * @param reader
         */
        public MyFileScoreProvider(IndexReader reader) {
            super(reader);
            try {
                filenames = FieldCache.DEFAULT.getStrings(reader, "filename");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
            //如何根据doc获取相应的field的值
            /**
             * 在reader没有关闭之前，所有的数据会有存储要一个域缓存中，可以通过域缓存获取很多有用的信息
             * filenames = FieldCache.DEFAULT.getStrings(reader, "filename"); 可以获取所有的filename域的信息
             */
            String fileName = filenames[doc];
            if (fileName.endsWith(".txt") || fileName.endsWith(".ini")) {
                return subQueryScore * 10;
            }
            return subQueryScore/5;
        }
    }

    private class MyCustomScoreQuery extends CustomScoreQuery {

        public MyCustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) {
            super(subQuery, valSrcQuery);
        }

        @Override
        protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {
            //默认情况实现的评分是通过原有的评分*传入进来的评分域所获取的评分来确定最终的打分的
            //为了根据不同的需求进行评分，需要自己进行评分的设定
            /**
             * 自定义评分的步骤
             * 创建一个类继承与CustomScoreProvider
             * 覆盖customeScore方法
             */
//            return super.getCustomScoreProvider(reader);
            return new MyCustomScoreProvider(reader);
        }
    }
    private class MyCustomScoreProvider extends CustomScoreProvider{

        /**
         * Creates a new instance of the provider class for the given {@link IndexReader}.
         *
         * @param reader
         */
        public MyCustomScoreProvider(IndexReader reader) {
            super(reader);
        }

        /**
         * subQueryScore 表示的是默认文档的打分
         * valSrcScore 表示的是评分域的打分
         * @param doc
         * @param subQueryScore
         * @param valSrcScore
         * @return
         * @throws IOException
         */
        @Override
        public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
//            return super.customScore(doc, subQueryScore, valSrcScore);
            return subQueryScore/valSrcScore;
        }
    }
}
